#include "log.hpp"
#include "Socket.hpp"
#include <sys/select.h>

const int default_fd = -1;
const int N = sizeof(fd_set) * 8;

class server
{
public:
    server(const add_in &addr)
    {
        _listen_socket = make_shared<Tcp_socket>();
        _listen_socket->Bulid_Server(addr);

        log(DEBUG, "Listen_sock: %d", _listen_socket->get_sockfd());

        // 初始化数组的值为 -1
        for (auto &e : arr)
        {
            e = default_fd;
        }

        arr[0] = _listen_socket->get_sockfd();
    }

    void Print()
    {
        cout << "Print()" << endl;
        int max = 0;
        for (int i = 0; i < N; i++)
        {
            if (arr[i] != default_fd)
            {
                cout << arr[i] << " ";
            }
            max = i;
        }
        cout << max;
        cout << endl;
    }

    void Run()
    {
        cout << "Run()" << endl;
        // 读取数组中的值,今天只处理 读取(read)操作

        while (1)
        {
            Print();
            int fd_max = -1; // 最大fd值
            fd_set read_set;
            FD_ZERO(&read_set);

            for (auto e : arr)
            {
                if (e != default_fd)
                {
                    FD_SET(e, &read_set);
                    if (e > fd_max)
                    {
                        fd_max = e;
                    }
                }
            }

            struct timeval time_out = {1, 0};

            cout << "fd_max: " << fd_max << endl;
            // 开始多路转接
            int n = select(fd_max + 1, &read_set, nullptr, nullptr, &time_out);
            switch (n)
            {
            case 0:
                log(INFO, "time out %d.%d", time_out.tv_sec, time_out.tv_usec);
                break;
            case -1:
                log(ERROR, "select error");
                return;
            default:
                log(DEBUG, "select success: %d", n);
                Loop(read_set);
            }
        }
    }

    void Loop(fd_set &read_set)
    {
        // 遍历每一个文件描述符并进行处理
        for (int i = 0; i < N; i++)
        {
            // 发生变化
            if (FD_ISSET(i, &read_set))
            {
                // 判断是否为listen套接字
                if (_listen_socket->get_sockfd() == i)
                {
                    listen_loop();
                }
                else
                {
                    ord_loop(i);
                }
            }
        }
    }

    void listen_loop()
    {
        sockaddr_in tmp;
        int n = _listen_socket->Accept_socket(&tmp);
        add_in addr(tmp);
        log(DEBUG, "new link come IP: %s, PORT: %d", addr.get_ip().c_str(), addr.get_port());

        // 将新到来的文件描述符加入到数组中
        // 寻找一个空位置进行插入
        for (auto &e : arr)
        {
            if (e == default_fd)
            {
                e = n;
                break;
            }
        }
    }

    void ord_loop(int fd)
    {
        cout << "ord_loop fd: " << fd; 
        // 进行数据通信，今天不做处理，将数据重新发回去
        char get_arr[1024];
        int n = recv(fd, get_arr, sizeof(arr) - 1, 0);
        if (n > 0)
        {
            get_arr[n] = 0;
            string ret_str = "server echo# ";
            ret_str += get_arr;
            send(fd, ret_str.c_str(), ret_str.size(), 0);
        }
        else if (n == 0)
        {
            log(DEBUG,"%d 断开连接",fd);
            // 断开了连接，从arr中删除
            close(fd);
            for(int i = 0; i < N ; i++)
            {
                if(arr[i] == fd)
                {
                    log(DEBUG,"i = %d arr[i] = %d fd = %d",i,arr[i],fd);
                    arr[i] = default_fd;
                    cout << "arr[i] = " << arr[i];
                    break;
                } 
            }
        }
        else
        {
            log(ERROR, "recv error");
        }
    }

private:
    socket_ptr _listen_socket;
    int arr[N];
};
